
def __make_directions():

    class Direction(int):
        """Compass direction. Invert (~) to get the inverse direction, add to it to
        turn clockwise, subtract for counter clockwise. Represented as an integer,
        but casts to string with str()"""
        def __add__(self, other): return Directions[(Directions.index(self) + other) % 4]
        def __sub__(self, other): return self + (4 - int(other) % 4)
        def __invert__(self): return self + 2
        def __str__(self): return ['North', 'East', 'South', 'West'][self]

    class DirectionsType(object):
        """Enum of compass directions - North, South, East, West. Iterable."""
        __slots__ = []
        North = property(lambda self: Directions[0])
        East  = property(lambda self: Directions[1])
        South = property(lambda self: Directions[2])
        West  = property(lambda self: Directions[3])
        def __iter__(self): return iter(Directions)

    Directions = [Direction(0), Direction(1), Direction(2), Direction(3)]
    return DirectionsType()

Directions = __make_directions()


if __name__ == '__main__':

    import unittest

    class DirectionsTest(unittest.TestCase):
        def testIncreaseDirection(self):
            """A direction increased, should be the direction turned clockwise"""
            assert Directions.North + 1 == Directions.East
            assert Directions.East + 1 == Directions.South
            assert Directions.South + 1 == Directions.West
            assert Directions.West + 1 == Directions.North
        def testDecreaseDirection(self):
            """A direction decreased, should be the direction turned counter-clockwise"""
            assert Directions.North - 1 == Directions.West
            assert Directions.West - 1 == Directions.South
            assert Directions.South - 1 == Directions.East
            assert Directions.East - 1 == Directions.North
        def testReverseDirection(self):
            """The inverse of a direction, should be the opposite direction"""
            assert ~Directions.North == Directions.South
            assert ~Directions.South == Directions.North
            assert ~Directions.East == Directions.West
            assert ~Directions.West == Directions.East
        def testIteration(self):
            """Directions should be iterable"""
            assert [str(dir) for dir in Directions] == ['North', 'East', 'South', 'West']

    unittest.main()

